package tr.mesir.dao;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.jboss.envers.DefaultRevisionEntity;
import org.jboss.envers.RevisionType;
import org.jboss.envers.VersionsReader;
import org.jboss.envers.VersionsReaderFactory;
import org.jboss.envers.query.VersionsRestrictions;
import org.springframework.stereotype.Repository;

import tr.mesir.domain.Contact;
import tr.mesir.domain.wrappers.ContactVersionWrapper;

/**
 * See AddressBookDAOImpl for detail on @Repository
 * 
 * @author mertcaliskan
 */
@Repository
public class ContactDAOImpl implements ContactDAO {

	@PersistenceContext
	protected EntityManager entityManager;

	/*
	 * The parameters for forRevisionsOfEntity are; Class, selectEntitiesOnly and selectDeletedEntities. 
	 * With selectEntitiesOnly set to true, the result of the query will be a list of entities only. 
	 * And with selecDeletedEntities, the revisions where the entity was deleted will be included in the result.
	 * 
	 * Here, by setting selectEntitiesOnly to false, we're getting a List of  Object[] that consist of 
	 * Contact, DefaultRevisionEntity, RevisionType. While iterating through it, a wrapper object is constructed 
	 * to handle the data decently in the UI layer.
	 */
	@SuppressWarnings("unchecked")
	public List<ContactVersionWrapper> getContactVersions(Long id) {
		VersionsReader reader = VersionsReaderFactory.get(entityManager);
		List<ContactVersionWrapper> revisionsWrapper = new ArrayList<ContactVersionWrapper>();

		List<Object[]> resultList = reader.createQuery().forRevisionsOfEntity(
				Contact.class, false, true).add(VersionsRestrictions.idEq(id))
				.getResultList();

		for (Object[] objects : resultList) {
			for (int i = 0; i < objects.length - 2; i = i + 2) {
				ContactVersionWrapper contactVersionWrapper = new ContactVersionWrapper(
						(Contact) objects[i],
						(DefaultRevisionEntity) objects[i + 1],
						(RevisionType) objects[i + 2]);
				revisionsWrapper.add(contactVersionWrapper);
			}
		}

		return revisionsWrapper;
	}

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}
}